/**
 *
 */
package common.util;

import org.apache.commons.lang.StringUtils;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * HTTP请求工具类
 *
 * @author WangXin
 */
public class HttpClient4Util {

    private static final Logger log = Logger.getLogger(HttpClient4Util.class);
    private static final CloseableHttpClient httpClient;

    private static HttpClient setHttpClient(HttpClient httpclient) {

        httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY,
                CookiePolicy.BROWSER_COMPATIBILITY);
        httpclient.getConnectionManager().closeIdleConnections(10,
                TimeUnit.SECONDS);
        httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
                HttpVersion.HTTP_1_1);
        httpclient.getParams().setParameter(
                CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.TRUE);
        httpclient.getParams().setParameter(
                CoreProtocolPNames.HTTP_CONTENT_CHARSET, HTTP.UTF_8);
        // httpclient.getParams().setParameter(AllClientPNames.CONN_MANAGER_TIMEOUT,1000);
        httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
                6000);
        httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 7000);

        return httpclient;
    }

    /**
     * 发送Get请求
     *
     * @param url
     * @return
     * @throws InterruptedException
     */
    public static String get(String url, Map<String, String> map) throws InterruptedException {
        log.info("Request Url:" + url + " params:" + map.toString());
        HttpClient httpclient = new DefaultHttpClient();
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        if (null != map) {
            for (String key : map.keySet()) {
                NameValuePair nvp = new BasicNameValuePair(key, map.get(key));
                nvps.add(nvp);
            }
        }
        setHttpClient(httpclient);
        String body = null;
        try {
            HttpEntity entity = null;
            for (int i = 0; i < 3; i++) {
                // Get请求
                HttpGet httpget = new HttpGet(url);
                // 设置参数
                String str = EntityUtils.toString(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
                httpget.setURI(new URI(httpget.getURI().toString() + "?" + str));
                // 调用私有的 发送请求
                entity = getUtis(httpget, httpclient);
                if (entity != null) {
                    break;
                } else {
                    if (i < 2) {
                        log.warn("reqest remote http failed.time count :" + i + 1);
                    } else {
                        log.error("reqest remote http failed.time count :" + i + 1);
                    }
                    Thread.sleep(100);
                    continue;
                }
            }
            body = EntityUtils.toString(entity);
            log.info("Response Result:" + body);
            if (entity != null) {
                entity.consumeContent();
            }
        } catch (ParseException e) {
            log.error(e.toString(), e);
        } catch (UnsupportedEncodingException e) {
            log.error(e.toString(), e);
        } catch (IOException e) {
            log.error(e.toString(), e);
        } catch (URISyntaxException e) {
            log.error(e.toString(), e);
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
        return body;
    }


    /**
     * 发送Get请求
     *
     * @param httpget
     * @param httpclient
     * @return
     */
    private static HttpEntity getUtis(HttpGet httpget, HttpClient httpclient) {
        HttpEntity entity = null;
        try {
            // 发送请求
            HttpResponse httpresponse = httpclient.execute(httpget);
            // 获取返回数据
            entity = httpresponse.getEntity();
        } catch (UnsupportedEncodingException e) {
            log.error(e.toString(), e);
        } catch (IOException e) {
            log.error(e.toString(), e);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return entity;

    }

    /**
     * 发送Get请求
     *
     * @param url
     * @param
     * @return
     * @throws IOException
     * @throws URISyntaxException
     * @throws InterruptedException
     */
    public static String get(String url) throws IOException, URISyntaxException, InterruptedException {
        log.info("Request Url:" + url);
        HttpClient httpclient = new DefaultHttpClient();
        setHttpClient(httpclient);
        String body = null;
        try {
            HttpGet httpget = new HttpGet(url);
            httpget.setURI(new URI(url));
            for (int i = 0; i < 3; i++) {
                try {
                    HttpEntity entity = getUtis(httpget, httpclient);
                    body = EntityUtils.toString(entity);
                    log.info("Response Result-[" + i + "]:" + body);
                    if (StringUtils.isBlank(body)) {
                        if (i < 2) {
                            log.warn("Http请求失败，错误" + i);
                        } else {
                            log.error("Http请求失败，错误" + i);
                        }
                        Thread.sleep(500);
                        continue;
                    }
                    if (entity != null) {
                        entity.consumeContent();
                    }
                    break;
                } catch (Exception e) {
                    if (i < 2) {
                        log.error(e.toString(), e);
                    } else {
                        log.error(e.toString(), e);
                    }
                    Thread.sleep(500);
                    continue;
                }
            }
        } catch (ParseException e) {
            log.error(e.toString(), e);
            throw new ParseException(e.toString());
        } catch (URISyntaxException e) {
            log.error(e.toString(), e);
            throw new URISyntaxException(e.getReason().toString(), e.getMessage().toString());
        } catch (Exception e) {
            log.error(e.toString(), e);
            throw new RuntimeException(e);
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
        return body;
    }

	/*public static String post(String url,Object obj)throws Exception{
        Map<String, String> paramMap = new HashMap<String, String>();
		paramMap.put(IConstants.PARAM_DATA,JSON.toJSONString(obj));
		return post(url,paramMap);
	}*/

    /**
     * post请求
     *
     * @param url
     * @param map
     * @return
     * @throws Exception
     */
    public static String post(String url, Map<String, Object> map) throws Exception {
        log.info("Request Url:" + url + " params:" + map.toString());
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        if (null != map) {
            for (String key : map.keySet()) {
                NameValuePair nvp = new BasicNameValuePair(key, map.get(key).toString());
                nvps.add(nvp);
            }
        }
        String result = "";
        HttpClient httpclient = new DefaultHttpClient();
        setHttpClient(httpclient);
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
        try {
            for (int i = 0; i < 3; i++) {
                try {
                    result = HttpClient4Util.postUnit(httpclient, httpPost);
                    log.info("Response result[" + i + "] " + result);
                    if (StringUtils.isBlank(result)) {
                        if (i < 2) {
                            log.warn("Http远程请求失败:" + i);
                        } else {
                            log.error("Http远程请求失败:" + i);
                        }
                        Thread.sleep(500);
                        continue;
                    }
                    break;
                } catch (Exception e) {
                    if (i < 2) {
                        log.warn(e);
                    } else {
                        log.error(e.toString(), e);
                    }
                    Thread.sleep(500);
                    continue;
                }
            }
        } catch (ParseException e) {
            log.error(e.toString(), e);
            throw new ParseException(e.toString());
        } catch (Exception e) {
            log.error(e.toString(), e);
            throw new RuntimeException(e);
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
        return result;
    }

    /*
     * 拆分post请求逻辑
     */
    private static String postUnit(HttpClient httpclient, HttpPost httpPost) throws Exception {
        HttpResponse httpResponse = null;
        String result = "";
        try {
            httpResponse = httpclient.execute(httpPost);
            result = EntityUtils.toString(httpResponse.getEntity());
        } catch (Exception e) {
            log.warn(e.toString(), e);
            throw new Exception(e);
        } finally {
            if (httpPost.isAborted()) {
                httpPost.abort();
            }
            //httpclient.getConnectionManager().shutdown();
        }
        return result;
    }

    /**
     * post请求
     *
     * @param url
     * @param
     * @return
     * @throws Exception
     */
    public static String postImg(byte[] imgbytes, String url, String path, String imageName) throws Exception {
        url = url + "&path=" + path + imageName;
        String result = "";
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "image/jpeg");
        HttpResponse httpResponse = null;
        HttpClient httpclient = new DefaultHttpClient();
        setHttpClient(httpclient);
        try {
            httpPost.setEntity(new ByteArrayEntity(imgbytes));
            httpResponse = httpclient.execute(httpPost);
            result = EntityUtils.toString(httpResponse.getEntity());
        } catch (Exception e) {
            log.error(e.toString(), e);
            throw new Exception(e);
        } finally {
            if (httpPost.isAborted()) {
                httpPost.abort();
            }
            httpclient.getConnectionManager().shutdown();
        }
        return result;
    }


    //功能: postBody形式发送数据
    //@param urlPath 对方地址
    //@param json 要传送的数据
    //@return
    //@throws Exception
    public static String postBody(String urlPath, String json) throws Exception {
        String body = "";
        try {
            log.info("Request Url:" + urlPath + "json:" + json);
            //创建httpclient对象
            CloseableHttpClient client = HttpClients.createDefault();
            //创建post方式请求对象
            HttpPost httpPost = new HttpPost(urlPath);
            StringEntity s = new StringEntity(json, HTTP.UTF_8);
            s.setContentType("application/json");
            //设置参数到请求对象中
            httpPost.setEntity(s);
            //设置header信息
            //指定报文头【Content-type】、【User-Agent】
            httpPost.setHeader("Content-type", "application/json;charset=UTF-8");
            httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //执行请求操作，并拿到结果（同步阻塞）
            CloseableHttpResponse response = client.execute(httpPost);
            //获取结果实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                //按指定编码转换结果实体为String类型
                body = EntityUtils.toString(entity, "UTF-8");
            }
            //System.out.println(body);
            log.info("Response Result:" + body);
            EntityUtils.consume(entity);
            //释放链接
            response.close();
            return body;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    public static String doGet(String url, Map<String, String> params) {
        return doGet(url, params, "UTF-8");
    }

    public static String doGet(String url, Map<String, String> params, String charset) {
        if (StringUtils.isBlank(url)) {
            return null;
        } else {
            try {
                if (params != null && !params.isEmpty()) {
                    ArrayList e = new ArrayList(params.size());
                    Iterator response = params.entrySet().iterator();

                    while (response.hasNext()) {
                        Map.Entry statusCode = (Map.Entry) response.next();
                        String entity = (String) statusCode.getValue();
                        if (entity != null) {
                            e.add(new BasicNameValuePair((String) statusCode.getKey(), entity));
                        }
                    }

                    url = url + "?" + EntityUtils.toString(new UrlEncodedFormEntity(e, charset));
                }

                HttpGet e1 = new HttpGet(url);
                CloseableHttpResponse response1 = httpClient.execute(e1);
                int statusCode1 = response1.getStatusLine().getStatusCode();
                if (statusCode1 != 200) {
                    e1.abort();
                    throw new RuntimeException("HttpClient,error status code :" + statusCode1);
                } else {
                    HttpEntity entity1 = response1.getEntity();
                    String result = null;
                    if (entity1 != null) {
                        result = EntityUtils.toString(entity1, "utf-8");
                    }

                    EntityUtils.consume(entity1);
                    response1.close();
                    return result;
                }
            } catch (Exception var8) {
                var8.printStackTrace();
                return null;
            }
        }
    }

    static {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(200);
        cm.setDefaultMaxPerRoute(50);
        RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(5000).setCircularRedirectsAllowed(true).build();
        httpClient = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(config).build();
    }
}
